package cn.uncode.dal.descriptor;

import java.io.Serializable;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;

import org.apache.commons.lang3.StringUtils;

import cn.uncode.dal.core.BaseDAL;
import cn.uncode.dal.utils.BeanUtil;
import cn.uncode.dal.utils.JsonUtils;

public class QueryResult implements Serializable {
    
    /**
     * 
     */
    private static final long serialVersionUID = 5675310807548144110L;
    
    private List<Map<String, Object>> copyForShardResult = new ArrayList<Map<String, Object>>();
    
    private List<Map<String, Object>> resultList;
    
    private Map<String, Object> resultMap;
    
    private Map<String, Object> page;
    
    /**
     * 添加分表查询结果集
     * @param shardResult 查询结果集
     */
    public void addShardResult(List<Map<String, Object>> shardResult){
    	copyForShardResult.addAll(shardResult);
    	if(resultList == null){
    		resultList = new ArrayList<>();
    	}
    	resultList.addAll(shardResult);
    }

    /**
     * 设置查询结果集
     * @param resultList 查询结果集
     */
    public void setResultList(List<Map<String, Object>> resultList) {
        this.resultList = resultList;
    }

    /**
     * 设置单条查询结果
     * @param resultMap 查询结果
     */
    public void setResultMap(Map<String, Object> resultMap) {
        this.resultMap = resultMap;
    }
    
    /**
     * 获取单条查询结果
     * @return 单条查询结果
     */
    public Map<String, Object> get(){
    	if(resultMap != null && resultMap.size() > 0){
    		return resultMap;
    	}
    	if(resultList != null && resultList.size() > 0){
    		return resultList.get(0);
    	}
        return resultMap;
    }
    
    /**
     * 获取单条查询结果并使用别名
     * <pre>
     * 示例：
     * 正常查询结果为：{"id":123456, "name":"Juny"}
     * 传入参数aliasName:
     * Map<String, String> aliasName = new HashMap<>();
     * aliasName.put("name", "userName");
     * 最终输出结果为：{"id":123456, "userName":"Juny"}
     * </pre>
     * @param aliasName 别名集合
     * @return 使用别名后的查询结果
     */
    public Map<String, Object> getWithAliasName(Map<String, String> aliasName){
    	Map<String, Object> result = get();
        return getResultWithAliasName(result, aliasName);
    }
    
    /**
     * 获取单条查询结果并使用别名或隐藏部分字段
     * <pre>
     * 示例：
     * 正常查询结果为：{"id":123456, "name":"Juny"}
     * 传入参数hiddenFields:
     * List<String> hiddenFields = new List<>();
     * hiddenFields.add("id");
     * 传入参数aliasName:
     * Map<String, String> aliasName = new HashMap<>();
     * aliasName.put("name", "userName");
     * 最终输出结果为：{"userName":"Juny"}
     * </pre>
     * @param hiddenFields 隐藏字段集合
     * @param aliasName 别名集合
     * @return 使用别名后的查询结果
     */
    public Map<String, Object> getWithAliasName(List<String> hiddenFields, Map<String, String> aliasName){
    	Map<String, Object> result = get(hiddenFields);
    	result = getResultWithAliasName(result, aliasName);
        return result;
    }
    
    /**
     * 获取单条查询结果并隐藏部分字段
     * <pre>
     * 示例：
     * 正常查询结果为：{"id":123456, "name":"Juny"}
     * 传入参数hiddenFields:
     * List<String> hiddenFields = new List<>();
     * hiddenFields.add("id");
     * 最终输出结果为：{"userName":"Juny"}
     * </pre>
     * @param hiddenFields 隐藏字段集合
     * @return 查询结果
     */
    public Map<String, Object> get(List<String> hiddenFields){
    	Map<String, Object> temp = get();
    	if(temp != null){
    		for(String field : hiddenFields){
    			if(temp.containsKey(field)){
    				temp.remove(field);
    			}
        	}
    	}
        return temp;
    }
    
    /**
     * 获取查询结果集
     * @param hiddenFields 隐藏字段集合
     * @return 查询结果集
     */
    public List<Map<String, Object>> getList(){
        return resultList;
    }
    
    /**
     * 获取查询结果集
     * <pre>
     * 示例：
     * 正常查询结果为：[{"id":123456, "name":"Juny"},{...}]
     * 传入参数hiddenFields:
     * List<String> hiddenFields = new List<>();
     * hiddenFields.add("id");
     * 最终输出结果为：[{"userName":"Juny"},{...}]
     * </pre>
     * @param hiddenFields 隐藏字段集合
     * @return 查询结果集
     */
    public List<Map<String, Object>> getList(List<String> hiddenFields){
    	if(hiddenFields != null && resultList != null){
    		for(String field : hiddenFields){
        		for(Map<String, Object> map : resultList){
        			if(map.containsKey(field)){
        				map.remove(field);
        			}
        		}
        	}
    	}
        return resultList;
    }
    
    @Deprecated
    public List<Map<String, Object>> getList(Map<String, String> aliasName){
        return getResultListWithAliasName(resultList, aliasName);
    }
    
    /**
     * 获取查询结果集并使用别名
     * <pre>
     * 示例：
     * 正常查询结果为：[{"id":123456, "name":"Juny"},{...}]
     * 传入参数aliasName:
     * Map<String, String> aliasName = new HashMap<>();
     * aliasName.put("name", "userName");
     * 最终输出结果为：[{"id":123456, "userName":"Juny"},{...}]
     * </pre>
     * @param aliasName 别名集合
     * @return 使用别名后的查询结果
     */
    public List<Map<String, Object>> getListWithAliasName(Map<String, String> aliasName){
    	if(aliasName != null && resultList != null){
    		resultList = getResultListWithAliasName(resultList, aliasName);
    	}
        return resultList;
    }
    
    @Deprecated
    public List<Map<String, Object>> getList(List<String> hiddenFields, Map<String, String> aliasName){
    	resultList = getList(hiddenFields);
    	resultList = getListWithAliasName(aliasName);
        return resultList;
    }
    
    /**
     * 获取查询结果集并使用别名或隐藏部分字段
     * <pre>
     * 示例：
     * 正常查询结果为：[{"id":123456, "name":"Juny"},{...}]
     * 传入参数hiddenFields:
     * List<String> hiddenFields = new List<>();
     * hiddenFields.add("id");
     * 传入参数aliasName:
     * Map<String, String> aliasName = new HashMap<>();
     * aliasName.put("name", "userName");
     * 最终输出结果为：[{"userName":"Juny"},{...}]
     * </pre>
     * @param hiddenFields 隐藏字段集合
     * @param aliasName 别名集合
     * @return 使用别名后的查询结果
     */
    public List<Map<String, Object>> getListWithAliasName(List<String> hiddenFields, Map<String, String> aliasName){
    	resultList = getList(hiddenFields);
    	resultList = getListWithAliasName(aliasName);
        return resultList;
    }
    
    /**
     * 获取单条查询结果并转化成指定对象
     * @param beanClass 要转换的目标对象类
     * @return 转换后的对象
     */
    public <T> T as(Class<T> beanClass){
    	Map<String, Object> result = get();
    	if(result != null){
    		return BeanUtil.mapToObj(result, beanClass);
    	}
        return null;
    }
    
    /**
     * 获取查询结果集并转换成目标对象
     * @param beanClass 要转换的目标对象类
     * @return 转换后结果集
     */
    public <T> List<T> asList(Class<T> beanClass){
        if(resultList != null){
        	return JsonUtils.mapListToObjList(resultList, beanClass);
        }
        return null;
    }
    
    public void clear(){
    	copyForShardResult.clear();
    	if(resultList != null){
    		resultList.clear();
    	}
    	if(resultMap != null){
    		resultMap.clear();
    	}
    	if(page != null){
    		page.clear();
    	}
    }

    /**
     * 获取分页结果，必须使用selectPageByCriteria方法才有数据
     * <pre>
     * {"pageIndex":1, "pageSize":30, "pageCount":12, "recordTotal":355}
     * pageIndex：当前页，最小为1，最大为pageCount
     * pageSize：每页记录数
     * pageCount：根据recordTotal和pageSize计算出来的总页数
     * recordTotal：数据库总记录数
     * </pre>
     * @return 分页结果
     */
	public Map<String, Object> getPage() {
		return page;
	}
	
	public void setPage(Map<String, Object> page) {
		this.page = page;
	}
	
    /**
     * 获取结果并转换成KSUDI分页格式
     * @return 分页结果
     */
	public Map<String, Object> getKSDPageInfo(int pageNum) {
        if (null == resultList) {
            return null;
        }
        Map<String, Object> findListMap = new HashMap<>();
        Map<String, Object> info = new HashMap<String, Object>();
        //获得分页信息
        //{recordTotal=13, pageCount=2, pageSize=10, pageIndex=1}
        if (null != page && page.size() > 0) {
            return null;
        }
        //总条数
        int recordTotal = (int) page.get(BaseDAL.RECORD_TOTAL_KEY);
        //总页数
        int pageCount = (int) page.get(BaseDAL.PAGE_COUNT_KEY);
        //是否有上一页
        Boolean hasPreviousPage = null;
        //是否有下一页
        Boolean hasNextPage = null;
        if (pageNum == 1) {
            hasPreviousPage = false;
        } else {
            hasPreviousPage = true;
            info.put("prePage", pageNum - 1);
        }
        if (pageNum + 1 > pageCount) {
            hasNextPage = false;
        } else {
            hasNextPage = true;
            info.put("nextPage", pageNum + 1);
        }
        int begin = 1;
        int end = pageCount;
        if (pageNum - 4 > 0) {
            begin = pageNum - 4;
        }
        if (pageCount < 8) {
            end = pageCount;
        } else if (pageNum + 3 < 8) {
            end = 8;
        } else if (pageNum + 3 < pageCount) {
            end = pageNum + 3;
        }
        //当前显示的页码
        List<Integer> navigatepageNums = new ArrayList<Integer>();
        for (int i = begin; i <= end; i++) {
            navigatepageNums.add(i);
        }
        info.put("total", recordTotal);
        info.put("pageNum", pageNum);
        info.put("hasPreviousPage", hasPreviousPage);
        info.put("hasNextPage", hasNextPage);
        info.put("navigatepageNums", navigatepageNums);
        info.put("pages", pageCount);
        
        findListMap.put("list", resultList);
        findListMap.put("page", info);
        
        return findListMap;
    }
    
	private Map<String, Object> getResultWithAliasName(Map<String, Object> result, Map<String, String> aliasName){
    	if(result != null && result.size() > 0 && null != aliasName){
    		for(Entry<String, String> item : aliasName.entrySet()){
    			if(StringUtils.isNotBlank(item.getKey()) && StringUtils.isNotBlank(item.getValue())){
    				result.put(item.getValue(), result.get(item.getKey()));
    				result.remove(item.getKey());
    			}
    		}
    	}
        return result;
    }
	
	private List<Map<String, Object>> getResultListWithAliasName(List<Map<String, Object>> result, Map<String, String> aliasName){
    	if(result != null && result.size() > 0 && null != aliasName){
    		for(Entry<String, String> item : aliasName.entrySet()){
    			for(Map<String, Object> map : result){
    				if(StringUtils.isNotBlank(item.getKey()) && StringUtils.isNotBlank(item.getValue())){
    					map.put(item.getValue(), map.get(item.getKey()));
    					map.remove(item.getKey());
        			}
    			}
    		}
    	}
        return result;
    }
    
}
